/*
 * File:   Node.h
 * Author: jcrada
 *
 * Created on April 4, 2009, 3:29 PM
 */

#ifndef _NODE_H
#define	_NODE_H

#include "defs.h"

#include <vector>
#include <assert.h>

#include <QtXml/QDomElement>
#include <QtXml/QDomDocument>

namespace jcrada {

    class Node {
    private:
        Node* _parent;
        int _arity;
        Node** _children;
        void init( );
    protected:

        void setParent( Node* parent ) {
            this->_parent = parent;
        }

        virtual void setChild( Node* child, int position ) {
            this->_children[position] = child;
        }

    public:
        Node( int arity );
        virtual ~Node( );
        
        virtual void moveTo( Node* parent, int position = -1 );
        virtual void remove( );
        virtual void removeChild( Node* child );

        Node* findNodeInSubtreeUsingBFS( int position ) ;
        virtual int findPositionInSubtreeUsingBFS( const Node* node ) const;

        virtual int getTreeSize( ) const;
        virtual Node* getRoot() ;

        virtual Node* clone( ) const;

        virtual std::string toString( ) const;
        virtual std::string toStringDown( int level = 0) const;
        virtual std::string toStringUp( ) const;
        virtual void toXml(QDomDocument& xml, QDomElement* parent = NULL) const;
        virtual std::string toXml() const;


        static int getDepth( const Node* node );
        static int main( int argc, char** argv );

        virtual int getArity( ) const {
            return this->_arity;
        }

        virtual Node* getParent( ) const {
            return this->_parent;
        }

        virtual bool isRoot( ) const {
            return (this->_parent == NULL);
        }

        virtual Node* getChild( int position )const {
            assert(position >= 0 && position < getArity());
            return _children[position];
        }

        virtual int getChildPosition( const Node* child ) const {
            for (int i = 0; i < getArity(); ++i) {
                if (getChild(i) == child) {
                    return i;
                }
            }
            return -1;
        }

        virtual int getDepth( ) const {
            return getDepth(this);
        }

        virtual int getNumberOfChildren() const{
            int result = 0;
            for (int i = 0 ; i < getArity() ; ++i){
                if (getChild(i) != NULL){
                    ++result;
                }
            }
            return result;
        }

        virtual bool canHaveAnotherChild() const{
            return getNumberOfChildren() < getArity();
        }
        
    };
}

#endif	/* _NODE_H */

